﻿Option Explicit On
Option Strict On

Imports System
Imports System.ServiceModel

Imports ACOMDirector
Imports ACOMDirector.Framework.Hardware

Namespace Framework.Hardware.Remoting

    ''' <summary>
    ''' The remotable wrapper for the StateManager
    ''' </summary>
    ''' <remarks></remarks>
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId:="Remotable")> _
    Public Class StateManagerRemotableWrapper

#Region " Private Members "

        Private m_Proxy As IStateManager 'The State Manager Proxy
        Private WithEvents m_Callbacks As StateManagerCallbacks 'The Callback Event Handler
        Private m_RemoteMode As Boolean = False
        Private m_Faulted As Boolean = False

        'WCF Objects
        Private WithEvents m_ChannelFactory As DuplexChannelFactory(Of IStateManager)

#End Region

#Region " Public Events "

        Public Event ChannelFault As EventHandler

        Public Event StateChanged As EventHandler
        Public Event ForwardPowerLedChanged As EventHandler(Of PowerLedEventArgs)
        Public Event ReflectedPowerLedChanged As EventHandler(Of PowerLedEventArgs)

#End Region

#Region " Constructor "

        ''' <summary>
        ''' Private Constructor
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub New()
        End Sub

#End Region

#Region " Shared Methods "

        ''' <summary>
        ''' Creates a new Remotable Wrapper that can be used locally or act as a WCF Singleton host
        ''' </summary>
        ''' <param name="ComPort"></param>
        ''' <param name="SupportsPowerOn"></param>
        ''' <param name="DeterminingOperateMode"></param>
        ''' <param name="RemotePowerOnMechanism"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function CreateStateManagerWrapper(ByVal ComPort As String, ByVal SupportsPowerOn As Boolean, ByVal DeterminingOperateMode As Boolean, ByVal RemotePowerOnMechanism As RemotePowerOnSystem) As StateManagerRemotableWrapper
            'Create the Remotable Wrapper
            Dim RemotableWrapper As New StateManagerRemotableWrapper

            'Create an instance of the statemanagerproxy and Callback handler
            Dim Proxy As New StateManagerProxy(ComPort, SupportsPowerOn, DeterminingOperateMode, RemotePowerOnMechanism)
            Dim Callbacks As New StateManagerCallbacks

            'Subscribe to local events
            Proxy.SubscribeEventsLocal(Callbacks)

            'Set the proxy and callback handler
            RemotableWrapper.m_Proxy = Proxy
            RemotableWrapper.m_Callbacks = Callbacks

            Return RemotableWrapper
        End Function

        ''' <summary>
        ''' Connects to a remote instance of the Remotable Wrapper
        ''' </summary>
        ''' <param name="binding"></param>
        ''' <param name="Endpoint"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function ConnectStateManagerWrapper(binding As System.ServiceModel.Channels.Binding, Endpoint As System.ServiceModel.EndpointAddress) As StateManagerRemotableWrapper
            'Create the Remotable Wrapper
            Dim RemotableWrapper As New StateManagerRemotableWrapper
            RemotableWrapper.m_RemoteMode = True

            'Create the callback handler
            Dim Callbacks As New StateManagerCallbacks
            RemotableWrapper.m_Callbacks = Callbacks

            'Create the WCF channel factory
            RemotableWrapper.m_ChannelFactory = New DuplexChannelFactory(Of IStateManager)(RemotableWrapper.m_Callbacks, binding, Endpoint)
            RemotableWrapper.m_ChannelFactory.Open()

            'Get the Remote IStateManager Instance
            Dim RemoteProxy As IStateManager = RemotableWrapper.m_ChannelFactory.CreateChannel
            AddHandler DirectCast(RemoteProxy, ICommunicationObject).Faulted, AddressOf RemotableWrapper.ChannelFaultedHandler

            RemotableWrapper.m_Faulted = False
            RemotableWrapper.m_Proxy = RemoteProxy

            'Subscribe to events
            Try
                RemotableWrapper.m_Proxy.SubscribeEvents()
            Catch ex As EndpointNotFoundException
                Return Nothing
            Catch ext As TimeoutException
                'TODO: Handle Timeouts Better
                Return Nothing
            End Try

            Return RemotableWrapper
        End Function

#End Region

#Region " Event Handlers "

        ''' <summary>
        ''' Something went wrong with the communication channel
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub ChannelFaultedHandler(sender As Object, e As System.EventArgs)
            m_Faulted = True
            RaiseEvent ChannelFault(Me, New EventArgs)
        End Sub

#End Region

#Region " Public Methods "

        ''' <summary>
        ''' Closes the connection with the remote instance
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub CloseRemoteConnection()
            If m_RemoteMode Then

                'Unsubscribe from events
                RemoveHandler DirectCast(m_Proxy, ICommunicationObject).Faulted, AddressOf ChannelFaultedHandler
                If DirectCast(m_Proxy, ICommunicationObject).State = CommunicationState.Opened And Not m_Faulted Then
                    m_Proxy.UnsubscribeEvents()
                    DirectCast(m_Proxy, ICommunicationObject).Close()
                End If

                m_Proxy = Nothing

                'Close the channel
                If m_ChannelFactory.State = CommunicationState.Opened And Not m_Faulted Then
                    m_ChannelFactory.Close()
                End If
                m_ChannelFactory = Nothing

            End If
        End Sub

#End Region

#Region " Public Properties "

        ''' <summary>
        ''' The Proxy Object instance
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Proxy As IStateManager
            Get
                Return m_Proxy
            End Get
        End Property

#End Region

#Region " Passthrough Properties "

        Public ReadOnly Property State As AmplifierState
            Get
                Return m_Proxy.GetState()
            End Get
        End Property

        Public ReadOnly Property UIState As UIState
            Get
                Return m_Proxy.GetUIState
            End Get
        End Property

        Public ReadOnly Property COMPortOpen As Boolean
            Get
                Return m_Proxy.GetCOMPortOpen
            End Get
        End Property

        Public ReadOnly Property SupportsRemotePowerOn As Boolean
            Get
                Return m_Proxy.GetSupportsRemotePowerOn
            End Get
        End Property

        Public Property COMPort As String
            Get
                Return m_Proxy.GetCOMPort
            End Get
            Set(value As String)
                m_Proxy.SetCOMPort(value)
            End Set
        End Property

#End Region

#Region " Passthrough Methods "

        Public Sub Connect()
            m_Proxy.Connect()
        End Sub

        Public Sub Disconnect()
            m_Proxy.Disconnect()
        End Sub

        Public Sub OnOff()
            m_Proxy.OnOff()
        End Sub

        Public Sub OperateStandby()
            m_Proxy.OperateStandby()
        End Sub

        Public Sub SelectAntenna0()
            m_Proxy.SelectAntenna0()
        End Sub

        Public Sub SelectAntenna1()
            m_Proxy.SelectAntenna1()
        End Sub

        Public Sub SelectAntenna2()
            m_Proxy.SelectAntenna2()
        End Sub

        Public Sub SelectAntenna3()
            m_Proxy.SelectAntenna3()
        End Sub

        Public Sub SelectAntenna4()
            m_Proxy.SelectAntenna4()
        End Sub

        Public Sub SelectAntenna5()
            m_Proxy.SelectAntenna5()
        End Sub

        Public Sub SelectAntenna6()
            m_Proxy.SelectAntenna6()
        End Sub

        Public Sub SelectAntenna7()
            m_Proxy.SelectAntenna7()
        End Sub

        Public Sub SelectAntenna8()
            m_Proxy.SelectAntenna8()
        End Sub

        Public Sub SelectAntenna9()
            m_Proxy.SelectAntenna9()
        End Sub

        Public Sub SetMetricA(Metric As MeasurementMetricType)
            m_Proxy.SetMetricA(Metric)
        End Sub

        Public Sub SetMetricB(Metric As MeasurementMetricType)
            m_Proxy.SetMetricB(Metric)
        End Sub

        Public Sub StartMeasuring(MetricA As MeasurementMetricType, MetricB As MeasurementMetricType)
            m_Proxy.StartMeasuring(MetricA, MetricB)
        End Sub

        Public Sub StopMeasuring()
            m_Proxy.StopMeasuring()
        End Sub

#End Region

#Region " Callback Event Handlers "

        Private Sub m_Callbacks_ForwardPowerLedChanged(sender As Object, e As PowerLedEventArgs) Handles m_Callbacks.ForwardPowerLedChanged
            RaiseEvent ForwardPowerLedChanged(sender, e)
        End Sub

        Private Sub m_Callbacks_ReflectedPowerLedChanged(sender As Object, e As PowerLedEventArgs) Handles m_Callbacks.ReflectedPowerLedChanged
            RaiseEvent ReflectedPowerLedChanged(sender, e)
        End Sub

        Private Sub m_Callbacks_StateChanged(sender As Object, e As System.EventArgs) Handles m_Callbacks.StateChanged
            RaiseEvent StateChanged(sender, e)
        End Sub

#End Region

    End Class

End Namespace